<template>
  <div class="hu-color-picker" :class="{ light: isLightTheme }" :style="{ width: totalWidth + 'px' }">
    <div class="color-set">
      <Saturation ref="saturationRef" :color="rgbString" :hsv="hsv" :size="attr.hueHeight" @selectSaturation="selectSaturation" />
      <Hue ref="hueRef" :hsv="hsv" :width="attr.hueWidth" :height="attr.hueHeight" @selectHue="selectHue" />
      <Alpha :color="rgbString" :rgba="rgba" :width="attr.hueWidth" :height="attr.hueHeight" @selectAlpha="selectAlpha" />
    </div>
    <div :style="{ height: attr.previewHeight + 'px' }" class="color-show">
      <Preview :color="rgbaString" :width="previewWidth" :height="attr.previewHeight" />
    </div>
    <Box name="HEX" :color="attr.modelHex" @inputColor="inputHex" />
    <Box name="RGBA" :color="attr.modelRgba" @inputColor="inputRgba" />
    <Colors :color="rgbaString" :colors-default="colorsDefault" :colors-history-key="colorsHistoryKey" @selectColor="selectColor" />
    <slot></slot>
  </div>
</template>

<script setup lang="ts">
import {
  ref,
  reactive,
  computed,
  nextTick,
  watch,
} from 'vue'
import { setColorValue, rgb2hex } from './composible'

import Saturation from './Saturation.vue'
import Hue from './Hue.vue'
import Alpha from './Alpha.vue'
import Preview from './Preview.vue'
import Box from './Box.vue'
import Colors from './Colors.vue'

const props = defineProps({
  color: {
    type: String,
    default: '#000000',
  },
  theme: {
    type: String,
    default: 'dark',
  },
  colorsDefault: {
    type: Array,
    default: () => [
      '#000000',
      '#FFFFFF',
      '#FF1900',
      '#F47365',
      '#FFB243',
      '#FFE623',
      '#6EFF2A',
      '#1BC7B1',
      '#00BEFF',
      '#2E81FF',
      '#5D61FF',
      '#FF89CF',
      '#FC3CAD',
      '#BF3DCE',
      '#8E00A7',
      'rgba(0,0,0,0)',
    ],
  },
  colorsHistoryKey: {
    type: String,
    default: 'vue-colorpicker-history',
  },
})
const saturationRef = ref()
const hueRef = ref()
const emit = defineEmits(['changeColor'])
const attr = reactive({
  hueWidth: 15,
  hueHeight: 152,
  previewHeight: 30,
  modelRgba: '',
  modelHex: '',
  r: 0,
  g: 0,
  b: 0,
  a: 1,
  h: 0,
  s: 0,
  v: 0,
})
const isLightTheme = computed(() => {
  return props.theme === 'light'
})
const totalWidth = computed(() => {
  return attr.hueHeight + (attr.hueWidth + 8) * 2
})
const previewWidth = computed(() => {
  return totalWidth.value
})
const rgba = computed(() => {
  return {
    r: attr.r,
    g: attr.g,
    b: attr.b,
    a: attr.a,
  }
})
const hsv = computed(() => {
  return {
    h: attr.h,
    s: attr.s,
    v: attr.v,
  }
})
const rgbString = computed(() => {
  return `rgb(${attr.r}, ${attr.g}, ${attr.b})`
})
const rgbaStringShort = computed(() => {
  return `${attr.r}, ${attr.g}, ${attr.b}, ${attr.a}`
})
const rgbaString = computed(() => {
  return `rgba(${rgbaStringShort.value})`
})
const hexString = computed(() => {
  return rgb2hex(rgba.value, true)
})

const selectSaturation = (color: any) => {
  setRGBAHSV(color)
  setText()
}
const selectHue = (color: any) => {
  setRGBAHSV(color)
  setText()
  nextTick(() => {
    saturationRef.value.renderColor()
    saturationRef.value.renderSlide()
  })
}
const selectAlpha = (a: any) => {
  attr.a = a
  setText()
}
const inputHex = (color: string) => {
  setRGBAHSV(color)
  attr.modelHex = color
  attr.modelRgba = rgbaStringShort.value
  nextTick(() => {
    saturationRef.value.renderColor()
    saturationRef.value.renderSlide()
    hueRef.value.renderSlide()
  })
}
const inputRgba = (color: string) => {
  setRGBAHSV(color)
  attr.modelHex = hexString.value
  attr.modelRgba = color
  nextTick(() => {
    saturationRef.value.renderColor()
    saturationRef.value.renderSlide()
    hueRef.value.renderSlide()
  })
}
const setText = () => {
  attr.modelHex = hexString.value
  attr.modelRgba = rgbaStringShort.value
}
const selectColor = (color: string) => {
  setRGBAHSV(color)
  setText()
  nextTick(() => {
    saturationRef.value.renderColor()
    saturationRef.value.renderSlide()
    hueRef.value.renderSlide()
  })
}

const watchRgbaChange = () => {
  emit('changeColor', {
    rgba: rgba.value,
    hsv: hsv.value,
    hex: attr.modelHex,
  })
}

watch([() => rgba.value], (newValue, old) => {
  watchRgbaChange()
})

const setRGBAHSV = (color: any) => {
  const {
    r: _r,
    g: _g,
    b: _b,
    a: _a,
    h: _h,
    s: _s,
    v: _v,
  } = setColorValue(color)
  attr.r = _r
  attr.g = _g
  attr.b = _b
  attr.a = _a
  attr.h = _h
  attr.s = _s
  attr.v = _v
}
//初始化执行
setRGBAHSV(props.color)
setText()
</script>

<style lang="scss">
.hu-color-picker {
  padding: 10px;
  background: #1d2024;
  border-radius: 4px;
  box-shadow: 0 0 16px 0 rgba(0, 0, 0, 0.16);
  z-index: 1;
  &.light {
    background: #f7f8f9;
    .color-type {
      .name {
        background: #e7e8e9;
      }
      .value {
        color: #666;
        background: #eceef0;
      }
    }
    .colors.history {
      border-top: 1px solid #eee;
    }
  }
  canvas {
    vertical-align: top;
  }
  .color-set {
    display: flex;
  }
  .color-show {
    margin-top: 8px;
    display: flex;
  }
}
</style>
